home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource3
/
123_01
/
ar1.bds
< prev
next >
Wrap
Text File
|
1985-03-11
|
14KB
|
790 lines
/*
archive - BDS C version
translated from Software Tools ar/ver1.rat by:
Oscar Goldman
1221 Knox Road
Wynnewood, PA 19096
converted to use BDS C library by:
Edward K. Ream
1850 Summit Ave.
Madison, WI 53705
(608) 231 -2952
version: May 5, 1982; February 24, 1983
*/
#include "bdscio.h"
#include "dio.h"
#include "date.h"
#define MAXLINE 300 /* maximum line size */
#define MAXCHARS 30
#define NEWLINE '\n'
#define EOS 0
#define YES 1
#define NO 0
#define MAXFILES 100 /* maximum number of files processable */
#define SYS_MAXFN 15
#define DELETE_CMD 'd' /* delete member from archive */
#define PRINT_CMD 'p' /* print archive members */
#define TABLE_CMD 't' /* print table of contents */
#define UPDATE_CMD 'u' /* update archive member */
#define VERBOSE_CMD 'v' /* controls amount of output */
#define EXTRACT_CMD 'x' /* extract archive member */
#define USAGE_MESSAGE "usage: ar1 [-](dptux)[v] archive [files]\n"
#define HEADER_STRING "#-h-"
#define TRAILER_STRING "#-t-"
#define NAMESIZE 20 /* size of name allowed in header */
/*
The following depend on a properly defined notion of file type.
All strings should be the same length.
*/
#define ASCII_STRING "ascii "
#define LOCAL_STRING "local "
#define BINARY_STRING "binary"
#define ASCII 0
#define LOCAL 1
#define BINARY 2
/*
The file size (in chars) is computed for storage in the
archive headers, although this information is not used.
*/
/* GLOBAL VARIABLES */
char *fname [MAXFILES]; /* list of file names */
int fstat [MAXFILES]; /* status of each name in list */
int fcount; /* number of files on the list */
char chead [MAXLINE]; /* current header */
int errcnt; /* error count */
int verbose; /* YES if verbose flag on */
main (argc,argv)
int argc;
char **argv;
{
_allocp = NULL;
dioinit(&argc, argv);
main1(argc, argv);
dioflush();
}
main1(argc, argv)
int argc;
char **argv;
{
char *archive, *command;
int i;
/* initialize global error count */
errcnt = 0;
/* make sure there is at least a command and an archive name */
if (argc < 3) {
fprintf(STD_ERR, "too few arguments\n");
error (USAGE_MESSAGE);
}
/*
Put a list of file names into fnames [].
Check for duplicates.
*/
get_fnames(argc, argv);
/* point at the name of the archive */
archive = argv [2];
upper (archive);
/* point at the options list */
command = argv [1];
lower (command);
/* skip leading '-' if present */
if (command [0] == '-') {
i = 1;
}
else {
i = 0;
}
if (command [i + 1] == VERBOSE_CMD) {
verbose = YES;
}
else if (command [i + 1] == EOS) {
verbose = NO;
}
else {
fprintf(STD_ERR, "option too long\n");
error (USAGE_MESSAGE);
}
if (command [i] == UPDATE_CMD) {
update (archive);
}
else if (command [i] == TABLE_CMD) {
table (archive);
}
else if (command [i] == EXTRACT_CMD || command [i] == PRINT_CMD) {
extract (archive, command [i]);
}
else if (command [i] == DELETE_CMD) {
delete (archive);
}
else {
fprintf(STD_ERR, "unknown option\n");
error (USAGE_MESSAGE);
}
}
/* Add file 'name' to archive open on 'fd' */
add_file (name, fd)
char *name;
int fd;
{
char head [MAXLINE], trail[MAXLINE];
int nfd;
char nfbuf [BUFSIZ];
/* kludge for BDS C fopen */
nfd = nfbuf;
if (fopen (name, nfbuf) == ERROR) {
fprintf(STD_ERR, "can't add %s\n", name);
errcnt++;
return;
}
if (errcnt == 0) {
make_header (head, name);
if (verbose == YES) {
fprintf(STD_OUT, "%s\n", name);
}
put_line (head, fd);
copy_in (nfd, fd);
make_trailer (head, trail);
put_line (trail, fd);
}
fclose (nfd);
}
/*
Copy a file into an archive.
May have to be adjusted to allow for binary files.
*/
copy_in (fd, afd)
int fd, afd;
{
int c;
while (1) {
/* allow abort with ^C from console */
chkkey();
c = getc(fd);
if (c == ERROR || c == CPMEOF) {
break;
}
putc (c, afd);
}
}
/* Copy archive element from one archive to another */
copy_ele (oldafd, newafd)
int oldafd, newafd;
{
char line [MAXLINE];
while (get_line (line, oldafd) != 0) {
put_line (line, newafd);
if (ele_end (line) == YES) {
return;
}
}
remark ("archive integrity in doubt - missing trailer.\n");
errcnt++;
}
/* Copy a file out of an archive */
copy_out (afd, fd)
int afd, fd;
{
char line [MAXLINE];
int start;
while (get_line (line, afd) != 0) {
if (ele_end (line) == YES) {
/* we've copied the whole archive element */
return;
}
else {
put_line (line, fd); /* ordinary text */
}
}
remark ("archive integrity in doubt - missing trailer.\n");
errcnt++;
}
/* Delete files from the archive */
delete (aname)
char *aname;
{
int tprefx;
char tname [SYS_MAXFN];
int afd, tfd;
char afbuf [BUFSIZ], tfbuf[BUFSIZ];
/* kludge for BDS C fopen, fcreat */
afd = afbuf;
tfd = tfbuf;
tprefx = 0;
if (fcount <= 0) {
error ("delete by name only.\n");
}
if (fopen (aname, afbuf) == ERROR) {
cant (aname);
}
mkunik (tprefx, tname);
if (fcreat (tname, tfbuf) == ERROR) {
fprintf(STD_ERR, "can not create %s\n", tname);
}
replace (afd, tfd, DELETE_CMD);
not_found ();
fclose (afd);
putc (CPMEOF, tfd);
fflush (tfd);
fclose (tfd);
if (errcnt == 0) {
unlink (aname);
rename (tname,aname);
}
else {
remark ("fatal errors - archive not altered.\n");
}
unlink (tname);
}
/* Extract files from archive */
extract (archive, cmd)
char *archive, cmd;
{
char name [SYS_MAXFN], hdr[MAXLINE];
int afd, fd;
char afbuf [BUFSIZ], fbuf[BUFSIZ];
/* kludge for BDS C fopen, fcreat */
afd = afbuf;
fd = fbuf;
if (fopen (archive, afbuf) == ERROR) {
fprintf(STD_ERR, "can not open archive: %s\n", archive);
exit();
}
/* NOTE: this code could be much improved by keeping track of the
* number of files that have been extracted and exiting
* when all have been found.
*/
while (get_header (afd, hdr, name) != EOF) {
if (file_arg (name) == NO) {
skipf (afd);
}
else {
if (verbose == YES && cmd == PRINT_CMD) {
fprintf(STD_OUT, "%s\n", name);
}
else if (verbose == YES) {
fprintf(STD_OUT, "%s\n", name);
}
if (cmd == PRINT_CMD) {
copy_out (afd, STD_OUT);
}
else {
if (fcreat (name, fbuf) != ERROR) {
copy_out (afd, fd);
putc (CPMEOF, fd);
fflush (fd);
fclose (fd);
}
else {
fprintf(STD_ERR,
"can not create %s\n", name);
errcnt++;
skipf (afd);
}
}
}
}
not_found();
}
/* See if name is present in argument list */
file_arg (name)
char *name;
{
int i;
/* a null list matches ALL files */
if (fcount <= 0) {
return (YES);
}
for (i = 0; i < fcount; i++) {
if (strcmp (name, fname [i]) == 0) {
fstat [i] = YES;
return (YES);
}
}
return (NO);
}
/* Determine size of file (in chars) */
unsigned
fsize (name)
char *name;
{
int fd;
char fbuf [BUFSIZ];
unsigned count;
char line [MAXLINE];
int n;
/* kludge for BDS C fopen */
fd = fbuf;
if (fopen (name, fbuf) == ERROR) {
return (ERROR);
}
count = 0;
while (n = get_line(line, fd)) {
count += n;
}
fclose (fd);
return (count);
}
/*
Get file names into 'fname', check for duplicates.
File names are stored LOWER CASE.
*/
get_fnames(argc, argv)
int argc;
char **argv;
{
int ap, fp, len, i;
char line [MAXLINE];
for (fp = 0, ap = 3; ap < argc; ap++) {
fname [fp] = argv[ap];
if (fname [fp][0] == '-' && fname [fp][1] == EOS) {
while (fp < MAXFILES) {
/* get list from standard input */
len = get_line (line, STD_IN);
if (len <= 1) {
break;
}
/* remove the NEWLINE */
line [len-1] =EOS;
/* save it in dynamic storage */
fname [fp] = strsav (line);
lower (fname [fp]);
fp++;
if (fp >= MAXFILES) {
error("too many file names\n");
}
}
}
else {
lower (fname [fp++]);
if (fp >= MAXFILES) {
error ("too many file names.\n");
}
}
}
/* set global count of the number of files. */
fcount = fp;
for (fp = 0; fp < fcount; fp++) {
fstat [fp] = NO;
}
for (fp = 0; fp < fcount-1; fp++) {
for (i = fp + 1; i < fcount; i++) {
if (strcmp (fname [fp], fname [i]) == 0) {
fprintf(STD_ERR,
"duplicate %s\n", fname [i]);
errcnt++;
}
}
}
if (errcnt != 0) {
error ("fatal errors - archive not altered.\n");
}
}
/* Get header information from archive member in 'fd' */
get_header (fd, hdr, name)
int fd;
char *hdr, *name;
{
char text [SYS_MAXFN],*hdrstr;
int index;
hdrstr = HEADER_STRING;
if (get_line (hdr, fd) == 0) {
return (EOF);
}
/* keep file names in LOWER case in header, trailer */
lower (hdr);
index = getwrd (hdr, text);
if (strcmp (text, hdrstr) != 0) {
remark ("archive not in proper format.\n");
errcnt++;
return (EOF);
}
save_header (hdr);
getwrd (hdr + index, name);
return (YES);
}
/*
Determine file type (ASCII, LOCAL, or BINARY).
There is no straight-forward way to do this in CP/M.
*/
get_ftype (name)
char *name;
{
return (ASCII);
}
/* Make header line for an archive member */
make_header (head, name)
char *head, *name;
{
int type, length;
char size [20], *now;
strcpy (head, HEADER_STRING);
strcat (head, " ");
strcat (head, name);
for (length = strlen(name) + 1; length <= NAMESIZE; length++) {
strcat (head, " ");
}
sprintf(size, "%11d", fsize(name));
strcat (head, size);
strcat (head, " ");
type = get_ftype (name);
if (type == ASCII) {
strcat (head, ASCII_STRING);
}
else if (type == LOCAL) {
strcat (head, LOCAL_STRING);
}
else if (type == BINARY) {
strcat (head, BINARY_STRING);
}
else {
strcat (head, ASCII_STRING);
}
strcat (head, " ");
now = getnow();
strcat (head, now);
strcat (head, "\n");
}
/* Make trailer line for an archive member */
make_trailer (head, trail)
char *trail, *head;
{
int index;
/* skip over header string */
index = getwrd (head, trail);
strcpy (trail, TRAILER_STRING);
strcat (trail, head + index);
}
/* Print 'not found' message if member isn't in archive */
not_found()
{
int i;
for (i = 0; i < fcount; i++) {
if (fstat [i] == NO) {
fprintf(STD_ERR, "%s not in archive.\n", fname [i]);
errcnt++;
}
}
}
/* See if string is end of archive element */
ele_end (str)
char *str;
{
int i;
char *tstr;
/* look for trailer string */
tstr = TRAILER_STRING;
for (i=0; tstr [i] != EOS; i++) {
if (tstr [i] != str[i]) {
return(NO);
}
}
/* compare str against name in the trailer */
str = skipbl (str + i);
if (strcmp(str, chead) == 0) {
return YES;
}
else {
return NO;
}
}
/* Replace or delete archive members */
replace (afd, tfd, cmd)
int afd, tfd;
char cmd;
{
char hdr [MAXLINE], name[SYS_MAXFN];
while (get_header (afd, hdr, name) != EOF) {
if (file_arg (name) == YES) {
if (cmd == UPDATE_CMD) {
add_file (name, tfd);
}
if (verbose == YES && cmd == DELETE_CMD) {
fprintf(STD_OUT, "%s\n", name);
}
skipf (afd);
}
else {
/* just copy. make no change */
fprintf(tfd, "%s", hdr);
copy_ele (afd, tfd);
}
}
}
/* Save current header in the global array chead [] */
save_header (head)
char *head;
{
int index;
/* skip header string */
index = getwrd (head, chead);
head = skipbl (head + index);
strcpy (chead, head);
}
/* Skip current archive element on file afd */
skipf (afd)
int afd;
{
char line [MAXLINE];
while (get_line (line, afd) != 0) {
if (ele_end (line) == YES) {
return;
}
}
remark ("archive integrity in doubt - missing trailer.\n");
errcnt++;
}
/* Print table of archive contents */
table (aname)
char *aname;
{
int afd;
char afbuf [BUFSIZ];
char hdr [MAXLINE], name[SYS_MAXFN];
/* kludge for BDS C fopen */
afd = afbuf;
if (fopen (aname, afbuf) == ERROR) {
cant (aname);
}
while (get_header (afd, hdr, name) != EOF) {
if (file_arg (name) == YES) {
tprint (hdr);
}
skipf (afd);
}
fclose (afd);
not_found();
}
/* Print table entry for one archive member */
tprint (hdr)
char *hdr;
{
char name [SYS_MAXFN];
int index;
/* skip over the header string */
index = getwrd (hdr, name);
/* put file name in name [], point i past name */
index += getwrd (hdr + index, name);
/* print the name */
fprintf(STD_OUT, "%s", name);
/* print other info from header only in verbose mode */
if (verbose == YES) {
for (; hdr [index] != NEWLINE && hdr [index] != EOS; index++) {
putc (hdr [index], STD_OUT);
}
}
/* end the line of information */
putc (NEWLINE, STD_OUT);
}
/* Update existing files, add new ones at end */
update (aname)
char *aname;
{
int afd, tfd;
char afbuf [BUFSIZ], tfbuf[BUFSIZ];
int fp;
int tprefx;
char tname [SYS_MAXFN];
/* kludge for BDS C fopen, fcreat routines */
afd = afbuf;
tfd = tfbuf;
tprefx = 0;
if (fopen (aname, afbuf) == ERROR) {
/* try to create a new archive */
if (fcreat (aname, afbuf) == ERROR) {
fprintf(STD_ERR, "can not create %s\n", aname);
}
putc(CPMEOF, afd);
fflush(afd);
fclose(afd);
if (fopen(aname, afbuf) == ERROR) {
cant(aname);
}
}
mkunik (tprefx, tname);
if (fcreat (tname, tfbuf) == ERROR) {
fprintf(STD_ERR, "can not create %s\n", tname);
}
/* update existing members */
replace (afd, tfd, UPDATE_CMD);
/* add new members */
for (fp = 0; fp < fcount; fp++) {
if (fstat [fp] == NO) {
add_file (fname [fp], tfd);
fstat [fp] = YES;
}
}
fclose (afd);
putc (CPMEOF, tfd);
fflush (tfd);
fclose (tfd);
if (errcnt == 0) {
unlink (aname);
rename (tname,aname);
}
else {
remark ("fatal errors - archive not altered.\n");
unlink (tname);
}
}
(aname);
rename (tname,aname);
}
else {
re